#include <iostream>
#include <string>
#include <cstring>
#include <set>
#include <cstdio>

class Command
{
public:
    Command()
    {
        _safe_command.insert("ls");
        _safe_command.insert("pwd");
        _safe_command.insert("whoami");
        _safe_command.insert("touch");
        _safe_command.insert("which");
    }

    bool SafeCheck(const std::string &cmdstr)
    {
        for (auto &cmd : _safe_command)
        {
            if ((strncmp(cmd.c_str(), cmdstr.c_str(), cmd.size())) == 0)
                return true;
        }
        return false;
    }

    std::string Excute(const std::string &cmdstr)
    {
        // Check
        if (!SafeCheck(cmdstr))
            return "unsafe";
        // Hand
        std::string result;
        FILE *fp = popen(cmdstr.c_str(), "r");
        if (fp)
        {
            char line[1024];
            while (fgets(line, sizeof(line), fp))
            {
                result += line;
            }
            return result.empty() ? "success" : result;
            // return result;
        }
        return "excute error";
    }

    void HandlerCommand(int sockfd, InetAddr addr)
    {
        while (true)
        {

            char cmdbuffer[1024];
            int n = ::recv(sockfd, cmdbuffer, sizeof(cmdbuffer) - 1, 0);
            if (n > 0)
            {
                cmdbuffer[n] = 0;
                printf("client info : %s, message is : %s\n", addr.AddrStr().c_str(), cmdbuffer);

                std::string result = Excute(cmdbuffer);

                ::send(sockfd, result.c_str(), result.size(), 0);
            }
            else if (n == 0)
            {
                printf("client %s quit\n", addr.AddrStr().c_str());
                break;
            }
            else
            {
                std::cout << "[FATAL]: recv error!!!" << std::endl;
                break;
            }
        }
    }

    ~Command()
    {
    }

private:
    std::set<std::string> _safe_command;
};